package org.javaforever.gatescore.core;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.gatescore.complexverb.FrontTwinsVerb;
import org.javaforever.gatescore.exception.ValidateException;
import org.javaforever.gatescore.utils.StringUtil;
import org.javaforever.gatescore.vue.DevEnvJs;
import org.javaforever.gatescore.vue.ElementUIHomePage;
import org.javaforever.gatescore.vue.EnJs;
import org.javaforever.gatescore.vue.ProdEnvJs;
import org.javaforever.gatescore.vue.SitEnvJs;
import org.javaforever.gatescore.vue.VuePageVars;
import org.javaforever.gatescore.vue.VueRouter;

public class FrontProject implements Comparable<FrontProject>,Cloneable,Serializable  {
	private static final long serialVersionUID = -7116108379537547563L;
	protected String standardName;
	protected String technicalstack;
	protected String folderPath = "/home/jerry/JerryWork/GatesCore/TestBed/source/";
	protected String templatesPath = "/home/jerry/git/GatesCore/GatesCore/templates/";
	protected Set<FrontPrism> prisms = new TreeSet<FrontPrism>();
	protected Set<FrontUtil> utils = new TreeSet<FrontUtil>();
	protected Set<FrontConfigFile> configFiles = new TreeSet<FrontConfigFile>();
	protected Set<FrontDomain> domains = new TreeSet<FrontDomain>();
	protected String sgsSource;
	protected String sqlSource;
	protected String label;
	protected String excelTemplateName = "";
	protected String excelTemplateFolder = "";
	protected String title = "";
	protected String subTitle = "";
	protected String footer = "";
	
	protected String backendProjectName = "";
	protected boolean showBackendProject = false;
	protected boolean useController = false;
	
	protected String controllerSuffix="controller";
	protected String controllerNamingSuffix = "Controller";
	protected String language = "chinese";
	
	public boolean isUseController() {
		return useController;
	}

	public void setUseController(boolean useController) {
		this.useController = useController;
	}

	@Override
	public int compareTo(FrontProject o) {
		return this.standardName.compareTo(o.getStandardName());
	}
	
	public ValidateInfo validate() {
		ValidateInfo info = new ValidateInfo();
		info.setSuccess(true);
		return info;
	}
	
	public void decorateMentuItems() {
		
	}
	
	public void decorateUserControllers() {
		boolean useController = this.isUseController();
		for (FrontPrism fp: this.prisms) {
			fp.getDomain().setUseController(useController);
			for (FrontManyToMany fmtm:fp.getManyToManies()) {
				fmtm.getMaster().setUseController(useController);
				fmtm.getSlave().setUseController(useController);
			}
			for (FrontTwinsVerb ftv: fp.getTwinsverbs()) {
				ftv.getMaster().setUseController(useController);
			}
		}
	}
	
	public  void writeToFile(String filePath, String content) throws Exception{
		File f = new File(filePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.createNewFile();
		try (Writer fw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(f.getAbsolutePath()),"UTF-8"))){			
	        fw.write(content,0,content.length());
		}
	}
	
	public void generateProjectFiles() throws Exception {
		ValidateInfo info = this.validate();
		if (info.success() == false) {
			throw new ValidateException(info);
		}
		decorateMentuItems();
		decorateUserControllers();
		String srcfolderPath = this.getFolderPath()+this.standardName+"/";
		if (this.getSgsSource() != null && !this.getSgsSource().equals("")) {
			writeToFile(srcfolderPath + "sgs/" + StringUtil.capFirst(this.getStandardName()) + "_original.sgs",
					this.getSgsSource());
		}
		
		File templatesfrom = new File(this.getTemplatesPath() + "FrontEndTemplates/");
		File templatesto = new File(srcfolderPath);
		
		FileCopyer copy = new FileCopyer();
		
		if (!StringUtil.isBlank(this.getExcelTemplateName())){				
			File mF1 = new File((this.getExcelTemplateFolder()+this.getExcelTemplateName()).replace("\\", "/"));
			File mF2 = new File((srcfolderPath+ "exceltemplate/"+this.getExcelTemplateName()).replace("\\", "/"));
			if (mF1.exists()){
				if (!mF2.getParentFile().exists()){
					mF2.getParentFile().mkdirs();
				}
				if (!mF2.exists()){
					mF2.createNewFile();
				}
				copy.copy(mF1.getPath(), mF2.getPath());
			}
		}	
		
		// 设置来源去向
		copy.dirFrom = templatesfrom;
		copy.dirTo = templatesto;
		copy.listFileInDir(templatesfrom);
		
		EnJs enjs = new EnJs();
		enjs.setStanadardName(this.standardName);
		writeToFile(srcfolderPath + "src/lang/en.js",
				enjs.generateStatementList().getContent());
		
		DevEnvJs devenvjs = new DevEnvJs();
		devenvjs.setUseController(this.isUseController());
		devenvjs.setShowBackendProject(this.showBackendProject);
		devenvjs.setBackendProjectName(this.backendProjectName);
		writeToFile(srcfolderPath + "config/"+devenvjs.getFileName(),
				devenvjs.generateStatementList().getContent());
		
		String [] controllerPackageSuffixs = this.getControllerSuffix().split(".");
		String  controllerPackageSuffix = "controller";
		if (controllerPackageSuffixs.length >= 1) controllerPackageSuffix = controllerPackageSuffixs[controllerPackageSuffixs.length-1];
		SitEnvJs sitenvjs = new SitEnvJs();
		sitenvjs.setUseController(this.isUseController());
		sitenvjs.setShowBackendProject(this.showBackendProject);
		sitenvjs.setBackendProjectName(this.backendProjectName);
		sitenvjs.setControllerPackageSuffix(controllerPackageSuffix);
		writeToFile(srcfolderPath + "config/"+sitenvjs.getFileName(),
				sitenvjs.generateStatementList().getContent());
		
		ProdEnvJs prodenvjs = new ProdEnvJs();
		prodenvjs.setUseController(this.isUseController());
		prodenvjs.setShowBackendProject(this.showBackendProject);
		prodenvjs.setBackendProjectName(this.backendProjectName);
		prodenvjs.setControllerPackageSuffix(controllerPackageSuffix);
		writeToFile(srcfolderPath + "config/"+prodenvjs.getFileName(),
				prodenvjs.generateStatementList().getContent());
		
		ElementUIHomePage hpage = new ElementUIHomePage();
		hpage.setLanguage(this.getLanguage());
		writeToFile(srcfolderPath + "src/views/pages/index.vue",
				hpage.generateStatementList().getContent());
		for (FrontPrism ps : this.prisms) {
			ps.setFolderPath(srcfolderPath);
			ps.generatePrismFiles();
		}
		VuePageVars pv = new VuePageVars();
		pv.setDomains(this.getDomains());
		writeToFile(srcfolderPath +"src/" +pv.getFileName(),
				pv.generateStatementList().getContent());
		
		VueRouter vr = new VueRouter();
		vr.setDomains(this.domains);
		for (FrontPrism fp:this.prisms) {
			vr.addMtms(fp.getManyToManies());
		}
		writeToFile(srcfolderPath + "src/router/modules/"+vr.getFileName(),
				vr.generateStatementList().getContent());
	}
	
	public static boolean delAllFile(String path) {
		boolean flag = false;
		File file = new File(path);
		if (!file.exists()) {
			return flag;
		}
		if (!file.isDirectory()) {
			return flag;
		}
		String[] tempList = file.list();
		File temp = null;
		for (int i = 0; i < tempList.length; i++) {
			if (path.endsWith(File.separator)) {
				temp = new File(path + tempList[i]);
			} else {
				temp = new File(path + File.separator + tempList[i]);
			}
			if (temp.isFile()) {
				temp.delete();
			}
			if (temp.isDirectory()) {
				delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
				delFolder(path + "/" + tempList[i]);// 再删除空文件夹
				flag = true;
			}
		}
		return flag;
	}

	
	public static void delFolder(String folderPath) {
		try {
			delAllFile(folderPath); // 删除完里面所有内容
			String filePath = folderPath;
			filePath = filePath.toString();
			java.io.File myFilePath = new java.io.File(filePath);
			myFilePath.delete(); // 删除空文件夹
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void generateProjectZip() throws Exception{
		delAllFile(this.folderPath+this.standardName+".zip");
		delFolder(this.getFolderPath()+this.standardName+"/");
		File f = new File(this.getFolderPath());
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		f.mkdirs();
				
		generateProjectFiles();
		ZipCompressor compressor = new ZipCompressor(this.folderPath+this.standardName+".zip");
		compressor.compressExe(this.getFolderPath()+this.standardName+"/");
		delFolder(this.getFolderPath()+this.standardName+"/");
	}
	
	public String getStandardName() {
		return standardName;
	}
	public void setStandardName(String standardName) {
		this.standardName = standardName;
	}
	public String getTechnicalstack() {
		return technicalstack;
	}
	public void setTechnicalstack(String technicalstack) {
		this.technicalstack = technicalstack;
	}
	public String getFolderPath() {
		return folderPath;
	}
	public void setFolderPath(String folderPath) {
		this.folderPath = folderPath;
	}
	public Set<FrontPrism> getPrisms() {
		return prisms;
	}
	public void setPrisms(Set<FrontPrism> prisms) {
		this.prisms = prisms;
	}
	public Set<FrontUtil> getUtils() {
		return utils;
	}
	public void setUtils(Set<FrontUtil> utils) {
		this.utils = utils;
	}
	public Set<FrontConfigFile> getConfigFiles() {
		return configFiles;
	}
	public void setConfigFiles(Set<FrontConfigFile> configFiles) {
		this.configFiles = configFiles;
	}
	public Set<FrontDomain> getDomains() {
		return domains;
	}
	public void setDomains(Set<FrontDomain> domains) {
		this.domains = domains;
	}
	public String getSgsSource() {
		return sgsSource;
	}
	public void setSgsSource(String sgsSource) {
		this.sgsSource = sgsSource;
	}
	public String getSqlSource() {
		return sqlSource;
	}
	public void setSqlSource(String sqlSource) {
		this.sqlSource = sqlSource;
	}
	public String getLabel() {
		return label;
	}
	public void setLabel(String label) {
		this.label = label;
	}
	public String getExcelTemplateName() {
		return excelTemplateName;
	}
	public void setExcelTemplateName(String excelTemplateName) {
		this.excelTemplateName = excelTemplateName;
	}
	public String getExcelTemplateFolder() {
		return excelTemplateFolder;
	}
	public void setExcelTemplateFolder(String excelTemplateFolder) {
		this.excelTemplateFolder = excelTemplateFolder;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getSubTitle() {
		return subTitle;
	}
	public void setSubTitle(String subTitle) {
		this.subTitle = subTitle;
	}
	public String getFooter() {
		return footer;
	}
	public void setFooter(String footer) {
		this.footer = footer;
	}

	public String getTemplatesPath() {
		return templatesPath;
	}

	public void setTemplatesPath(String templatesPath) {
		this.templatesPath = templatesPath;
	}

	public String getBackendProjectName() {
		return backendProjectName;
	}

	public void setBackendProjectName(String backendProjectName) {
		this.backendProjectName = backendProjectName;
	}

	public boolean isShowBackendProject() {
		return showBackendProject;
	}

	public void setShowBackendProject(boolean showBackendProject) {
		this.showBackendProject = showBackendProject;
	}

	public void putAllDomains(List<FrontDomain> domainList) {
		this.domains.clear();
		this.domains.addAll(domainList);		
	}

	/**
	 * 
	 * 从JAR中复制文件到磁盘	 * 
	 * @param srcFilePath：源路径，既JAR包中的资源文件，路径相对于CLASSPATH 
	 * @param destFilePath：目标路径，磁盘上的任意路径，绝对路径（一般为用户选择的文件夹路径）
	 * @return int：返回执行后的状态；0：失败；1：成功；（可以扩充其它状态）
	 * 
	 */

	public static int fileCopy(String srcFilePath, String destFilePath) {
		int flag = 0;
		File destFile = new File(destFilePath);

		try {
			BufferedInputStream fis = new BufferedInputStream(ClassLoader.getSystemResourceAsStream(srcFilePath));
			FileOutputStream fos = new FileOutputStream(destFile);
			byte[] buf = new byte[1024];
			int c = 0;
			while ((c = fis.read(buf)) != -1) {
				fos.write(buf, 0, c);
			}

			fis.close();

			fos.close();

			flag = 1;

		} catch (IOException e) {

			e.printStackTrace();

		}

		return flag;

	}

	public String getControllerSuffix() {
		return controllerSuffix;
	}

	public void setControllerSuffix(String controllerSuffix) {
		this.controllerSuffix = controllerSuffix;
	}

	public String getControllerNamingSuffix() {
		return controllerNamingSuffix;
	}

	public void setControllerNamingSuffix(String controllerNamingSuffix) {
		this.controllerNamingSuffix = controllerNamingSuffix;
	}

	public String getLanguage() {
		return language;
	}

	public void setLanguage(String language) {
		this.language = language;
	}

}
